package sistemadeproyectos;

import java.util.*;
import java.io.*;

/**
 * @author Giancarlo Nebiolo, 06-39965
 * @author Antonio Mundo, 06-39956
 * @autor Angel Rubio, 06-40263
 * @version 1.0
 * 
 * Creada el 1 de febrero del 2012, Clase encargada representar la sala de chat.
 * Estructurada por la lista de usuarios de una sala de chat asi como 
 * la lista de las salidas de comunicacion los clientes. Provee metodos para 
 * difundir mensajes a todos los miembros de la sala de chat, agregar usuarios,
 * eliminarlos y determinar si la sala de chat a la que representa contiene un
 * unico usuario (para efectos de determinar cuando eliminar la sala de chat).
 */
public class Chatroom {
    
    /**Contiene los nombres de los usuarios asociados a la sala de chat**/
    private HashSet<String> usuarios;
    
    /**Contiene la lista de flujo de salida de objetos de cada socket de los
     usuarios asociados a la sala de chat**/
    private ArrayList<ObjectOutputStream> sockets;

    /**Contructor de la clase Chatroom sin parametros**/
    public Chatroom() {
        this.sockets = new ArrayList<ObjectOutputStream>();
        this.usuarios = new HashSet<String>();
    }
    
    /**
     * Constructor de la clase Chatroom que agraga al usuario especificado. 
     * El usuario agregado podra mandar y recibir mas mensajes de otros
     * usuarios de esta instancia de chatroom.
     * @param creador La salida de datos del socket del cliente.
     * @param usuario El nombre del usuario.
     */
    public Chatroom(ObjectOutputStream creador, String usuario) {
        this.sockets = new ArrayList<ObjectOutputStream>();
        this.usuarios = new HashSet<String>();
        (this.sockets).add(creador);
        (this.usuarios).add(usuario);
        this.enviarMensaje(usuario+" se ha conectado.", 
                 (new ArrayList<String>(this.usuarios)));
    }
    
    /**
     * Metodo usado para agregar a un usuario en esta instancia de chatroom. 
     * El usuario agregado podra mandar y recibir mensajes de otros
     * usuarios de esta instancia de chatroom.
     * @param salida La salida de datos del socket del cliente.
     * @param usuario El nombre del usuario.
     */
    public synchronized boolean agregarUsuario(ObjectOutputStream salida, String usuario) {
        if (((this.usuarios).contains(usuario)) == false) {
            (this.sockets).add(salida);
            (this.usuarios).add(usuario);
            this.enviarMensaje(usuario+" se ha conectado.", 
                    (new ArrayList<String>(this.usuarios)));
            return true;
        }
        else { return false; }
    }
    
    /**
     * Metodo usado para eliminar un usuario en esta instancia de chatroom. 
     * El usuario eliminado no podra mandar ni recibir mas mensajes a otros
     * usuarios de esta instancia de chatroom.
     * @param salida La salida de datos del socket del cliente.
     * @param usuario El nombre del usuario.
     */
    public synchronized boolean unicoUsuario() {
        if (((this.sockets).size()) == 1) { return true; }
        else { return false; }
    }
    
    /**
     * Metodo usado para eliminar un usuario en esta instancia de chatroom. 
     * El usuario eliminado no podra mandar ni recibir mas mensajes a otros
     * usuarios de esta instancia de chatroom.
     * @param salida La salida de datos del socket del cliente.
     * @param usuario El nombre del usuario.
     */
    public synchronized void eliminarUsuario(ObjectOutputStream salida, String usuario) {
        (this.sockets).remove(salida); //se puede mejorar removiendo por indice
        (this.usuarios).remove(usuario);
        this.enviarMensaje(usuario+" se ha desconectado.",
                (new ArrayList<String>(this.usuarios)));
    }
    
    /**
     * Verifica si esta instancia de Chatroom contiene algun usuario conectado
     * a ella.
     * @return True si esta instancia de Chatroom no tiene ningun usuario
     * contenido.
     */
    public synchronized boolean estaVacia() {
        return (((this.usuarios).isEmpty()) ? true : false);
    }
    
   /**
     * Metodo usado para enviar un mensaje a todos los usuarios contenidos en 
     * esta instancia de chatroom
     * @param mensaje El mensaje que se desea difundir a todos los usuarios.
     */
    public synchronized void enviarMensaje(String mensaje, ArrayList<String> Usuarios) {
        Iterator<ObjectOutputStream> salida_usr = (this.sockets).iterator();
        while (salida_usr.hasNext()) {
            try {
                ObjectOutputStream envio = salida_usr.next();
                envio.writeObject(mensaje);
                envio.writeObject(Usuarios);
                envio.flush();
            }
            catch(IOException E){}
        }
    }
    
}
